home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / patch-2.1 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-20  |  9.8 KB  |  441 lines

  1. #include "EXTERN.h"
  2. #include "common.h"
  3. #include "INTERN.h"
  4. #include "util.h"
  5. #include "backupfile.h"
  6.  
  7. void my_exit();
  8.  
  9. #ifndef HAVE_STRERROR
  10. static char *
  11. private_strerror (errnum)
  12.      int errnum;
  13. {
  14.   extern char *sys_errlist[];
  15.   extern int sys_nerr;
  16.  
  17.   if (errnum > 0 && errnum <= sys_nerr)
  18.     return sys_errlist[errnum];
  19.   return "Unknown system error";
  20. }
  21. #define strerror private_strerror
  22. #endif /* !HAVE_STRERROR */
  23.  
  24. /* Rename a file, copying it if necessary. */
  25.  
  26. int
  27. move_file(from,to)
  28. char *from, *to;
  29. {
  30.     char bakname[512];
  31.     Reg1 char *s;
  32.     Reg2 int i;
  33.     Reg3 int fromfd;
  34.  
  35.     /* to stdout? */
  36.  
  37.     if (strEQ(to, "-")) {
  38. #ifdef DEBUGGING
  39.     if (debug & 4)
  40.         say2("Moving %s to stdout.\n", from);
  41. #endif
  42.     fromfd = open(from, 0);
  43.     if (fromfd < 0)
  44.         pfatal2("internal error, can't reopen %s", from);
  45.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  46.         if (write(1, buf, i) != 1)
  47.         pfatal1("write failed");
  48.     Close(fromfd);
  49.     return 0;
  50.     }
  51.  
  52.     if (origprae) {
  53.     Strcpy(bakname, origprae);
  54.     Strcat(bakname, to);
  55.     } else {
  56. #ifndef NODIR
  57.     char *backupname = find_backup_file_name(to);
  58.     if (backupname == (char *) 0)
  59.         fatal1("out of memory\n");
  60.     Strcpy(bakname, backupname);
  61.     free(backupname);
  62. #else /* NODIR */
  63. #ifdef __MSDOS__
  64.     /* if you have a three-letter extension, the source file gets
  65.        silently hosed, so put the ~ a the beginning */
  66.         Strcpy(bakname, simple_backup_suffix);
  67.     Strcat(bakname, to);
  68. #else /* __MSDOS__ */
  69.     Strcpy(bakname, to);
  70.         Strcat(bakname, simple_backup_suffix);
  71. #endif /* ?__MSDOS__ */
  72. #endif /* NODIR */
  73.     }
  74.  
  75.     if (stat(to, &filestat) == 0) {    /* output file exists */
  76.     dev_t to_device = filestat.st_dev;
  77.     ino_t to_inode  = filestat.st_ino;
  78.     char *simplename = bakname;
  79.     
  80.     for (s=bakname; *s; s++) {
  81.         if (*s == '/')
  82.         simplename = s+1;
  83.     }
  84.     /* Find a backup name that is not the same file.
  85.        Change the first lowercase char into uppercase;
  86.        if that isn't sufficient, chop off the first char and try again.  */
  87.     while (stat(bakname, &filestat) == 0 &&
  88.         to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  89.         /* Skip initial non-lowercase chars.  */
  90.         for (s=simplename; *s && !islower(*s); s++) ;
  91.         if (*s)
  92.         *s = toupper(*s);
  93.         else
  94.         Strcpy(simplename, simplename+1);
  95.     }
  96.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  97. #ifdef DEBUGGING
  98.     if (debug & 4)
  99.         say3("Moving %s to %s.\n", to, bakname);
  100. #endif
  101.     if (rename(to, bakname) < 0) {
  102.         say4("Can't backup %s, output is in %s: %s\n", to, from,
  103.          strerror(errno));
  104.         return -1;
  105.     }
  106.     while (unlink(to) >= 0) ;
  107.     }
  108. #ifdef DEBUGGING
  109.     if (debug & 4)
  110.     say3("Moving %s to %s.\n", from, to);
  111. #endif
  112.     if (rename(from, to) < 0) {        /* different file system? */
  113.     Reg4 int tofd;
  114.     
  115.     tofd = creat(to, 0666);
  116.     if (tofd < 0) {
  117.         say4("Can't create %s, output is in %s: %s\n",
  118.           to, from, strerror(errno));
  119.         return -1;
  120.     }
  121.     fromfd = open(from, 0);
  122.     if (fromfd < 0)
  123.         pfatal2("internal error, can't reopen %s", from);
  124.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  125.         if (write(tofd, buf, i) != i)
  126.         pfatal1("write failed");
  127.     Close(fromfd);
  128.     Close(tofd);
  129.     }
  130.     Unlink(from);
  131.     return 0;
  132. }
  133.  
  134. /* Copy a file. */
  135.  
  136. void
  137. copy_file(from,to)
  138. char *from, *to;
  139. {
  140.     Reg3 int tofd;
  141.     Reg2 int fromfd;
  142.     Reg1 int i;
  143.     
  144.     tofd = creat(to, 0666);
  145.     if (tofd < 0)
  146.     pfatal2("can't create %s", to);
  147.     fromfd = open(from, 0);
  148.     if (fromfd < 0)
  149.     pfatal2("internal error, can't reopen %s", from);
  150.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  151.     if (write(tofd, buf, i) != i)
  152.         pfatal2("write to %s failed", to);
  153.     Close(fromfd);
  154.     Close(tofd);
  155. }
  156.  
  157. /* Allocate a unique area for a string. */
  158.  
  159. char *
  160. savestr(s)
  161. Reg1 char *s;
  162. {
  163.     Reg3 char *rv;
  164.     Reg2 char *t;
  165.  
  166.     if (!s)
  167.     s = "Oops";
  168.     t = s;
  169.     while (*t++);
  170.     rv = malloc((MEM) (t - s));
  171.     if (rv == Nullch) {
  172.     if (using_plan_a)
  173.         out_of_mem = TRUE;
  174.     else
  175.         fatal1("out of memory\n");
  176.     }
  177.     else {
  178.     t = rv;
  179.     while (*t++ = *s++);
  180.     }
  181.     return rv;
  182. }
  183.  
  184. #if defined(lint) && defined(CANVARARG)
  185.  
  186. /*VARARGS ARGSUSED*/
  187. say(pat) char *pat; { ; }
  188. /*VARARGS ARGSUSED*/
  189. fatal(pat) char *pat; { ; }
  190. /*VARARGS ARGSUSED*/
  191. pfatal(pat) char *pat; { ; }
  192. /*VARARGS ARGSUSED*/
  193. ask(pat) char *pat; { ; }
  194.  
  195. #else
  196.  
  197. /* Vanilla terminal output (buffered). */
  198.  
  199. void
  200. say(pat,arg1,arg2,arg3)
  201. char *pat;
  202. long arg1,arg2,arg3;
  203. {
  204.     fprintf(stderr, pat, arg1, arg2, arg3);
  205.     Fflush(stderr);
  206. }
  207.  
  208. /* Terminal output, pun intended. */
  209.  
  210. void                /* very void */
  211. fatal(pat,arg1,arg2,arg3)
  212. char *pat;
  213. long arg1,arg2,arg3;
  214. {
  215.     fprintf(stderr, "patch: **** ");
  216.     fprintf(stderr, pat, arg1, arg2, arg3);
  217.     my_exit(1);
  218. }
  219.  
  220. /* Say something from patch, something from the system, then silence . . . */
  221.  
  222. void                /* very void */
  223. pfatal(pat,arg1,arg2,arg3)
  224. char *pat;
  225. long arg1,arg2,arg3;
  226. {
  227.     int errnum = errno;
  228.  
  229.     fprintf(stderr, "patch: **** ");
  230.     fprintf(stderr, pat, arg1, arg2, arg3);
  231.     fprintf(stderr, ": %s\n", strerror(errnum));
  232.     my_exit(1);
  233. }
  234.  
  235. /* Get a response from the user, somehow or other. */
  236.  
  237. void
  238. ask(pat,arg1,arg2,arg3)
  239. char *pat;
  240. long arg1,arg2,arg3;
  241. {
  242.     int ttyfd;
  243.     int r;
  244.     bool tty2 = isatty(2);
  245.  
  246.     Sprintf(buf, pat, arg1, arg2, arg3);
  247.     Fflush(stderr);
  248.     write(2, buf, strlen(buf));
  249.     if (tty2) {                /* might be redirected to a file */
  250.     r = read(2, buf, sizeof buf);
  251.     }
  252.     else if (isatty(1)) {        /* this may be new file output */
  253.     Fflush(stdout);
  254.     write(1, buf, strlen(buf));
  255.     r = read(1, buf, sizeof buf);
  256.     }
  257.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  258.                     /* might be deleted or unwriteable */
  259.     write(ttyfd, buf, strlen(buf));
  260.     r = read(ttyfd, buf, sizeof buf);
  261.     Close(ttyfd);
  262.     }
  263.     else if (isatty(0)) {        /* this is probably patch input */
  264.     Fflush(stdin);
  265.     write(0, buf, strlen(buf));
  266.     r = read(0, buf, sizeof buf);
  267.     }
  268.     else {                /* no terminal at all--default it */
  269.     buf[0] = '\n';
  270.     r = 1;
  271.     }
  272.     if (r <= 0)
  273.     buf[0] = 0;
  274.     else
  275.     buf[r] = '\0';
  276.     if (!tty2)
  277.     say1(buf);
  278. }
  279. #endif /* lint */
  280.  
  281. /* How to handle certain events when not in a critical region. */
  282.  
  283. void
  284. set_signals(reset)
  285. int reset;
  286. {
  287. #ifndef lint
  288.     static RETSIGTYPE (*hupval)(),(*intval)();
  289.  
  290.     if (!reset) {
  291.     hupval = signal(SIGHUP, SIG_IGN);
  292.     if (hupval != SIG_IGN)
  293.         hupval = (RETSIGTYPE(*)())my_exit;
  294.     intval = signal(SIGINT, SIG_IGN);
  295.     if (intval != SIG_IGN)
  296.         intval = (RETSIGTYPE(*)())my_exit;
  297.     }
  298.     Signal(SIGHUP, hupval);
  299.     Signal(SIGINT, intval);
  300. #endif
  301. }
  302.  
  303. /* How to handle certain events when in a critical region. */
  304.  
  305. void
  306. ignore_signals()
  307. {
  308. #ifndef lint
  309.     Signal(SIGHUP, SIG_IGN);
  310.     Signal(SIGINT, SIG_IGN);
  311. #endif
  312. }
  313.  
  314. /* Make sure we'll have the directories to create a file.
  315.    If `striplast' is TRUE, ignore the last element of `filename'.  */
  316.  
  317. void
  318. makedirs(filename,striplast)
  319. Reg1 char *filename;
  320. bool striplast;
  321. {
  322.     char tmpbuf[256];
  323.     Reg2 char *s = tmpbuf;
  324.     char *dirv[20];        /* Point to the NULs between elements.  */
  325.     Reg3 int i;
  326.     Reg4 int dirvp = 0;        /* Number of finished entries in dirv. */
  327.  
  328.     /* Copy `filename' into `tmpbuf' with a NUL instead of a slash
  329.        between the directories.  */
  330.     while (*filename) {
  331.     if (*filename == '/') {
  332.         filename++;
  333.         dirv[dirvp++] = s;
  334.         *s++ = '\0';
  335.     }
  336.     else {
  337.         *s++ = *filename++;
  338.     }
  339.     }
  340.     *s = '\0';
  341.     dirv[dirvp] = s;
  342.     if (striplast)
  343.     dirvp--;
  344.     if (dirvp < 0)
  345.     return;
  346.  
  347.     strcpy(buf, "mkdir");
  348.     s = buf;
  349.     for (i=0; i<=dirvp; i++) {
  350.     struct stat sbuf;
  351.  
  352.     if (stat(tmpbuf, &sbuf) && errno == ENOENT) {
  353.         while (*s) s++;
  354.         *s++ = ' ';
  355.         strcpy(s, tmpbuf);
  356.     }
  357.     *dirv[i] = '/';
  358.     }
  359.     if (s != buf)
  360.     system(buf);
  361. }
  362.  
  363. /* Make filenames more reasonable. */
  364.  
  365. char *
  366. fetchname(at,strip_leading,assume_exists)
  367. char *at;
  368. int strip_leading;
  369. int assume_exists;
  370. {
  371.     char *fullname;
  372.     char *name;
  373.     Reg1 char *t;
  374.     char tmpbuf[200];
  375.     int sleading = strip_leading;
  376.  
  377.     if (!at)
  378.     return Nullch;
  379.     while (isspace(*at))
  380.     at++;
  381. #ifdef DEBUGGING
  382.     if (debug & 128)
  383.     say4("fetchname %s %d %d\n",at,strip_leading,assume_exists);
  384. #endif
  385.     if (strnEQ(at, "/dev/null", 9))    /* so files can be created by diffing */
  386.     return Nullch;            /*   against /dev/null. */
  387.     name = fullname = t = savestr(at);
  388.  
  389.     /* Strip off up to `sleading' leading slashes and null terminate.  */
  390.     for (; *t && !isspace(*t); t++)
  391.     if (*t == '/')
  392.         if (--sleading >= 0)
  393.         name = t+1;
  394.     *t = '\0';
  395.  
  396.     /* If no -p option was given (957 is the default value!),
  397.        we were given a relative pathname,
  398.        and the leading directories that we just stripped off all exist,
  399.        put them back on.  */
  400.     if (strip_leading == 957 && name != fullname && *fullname != '/') {
  401.     name[-1] = '\0';
  402.     if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) {
  403.         name[-1] = '/';
  404.         name=fullname;
  405.     }
  406.     }
  407.  
  408.     name = savestr(name);
  409.     free(fullname);
  410.  
  411.     if (stat(name, &filestat) && !assume_exists) {
  412.     char *filebase = basename(name);
  413.     int pathlen = filebase - name;
  414.  
  415.     /* Put any leading path into `tmpbuf'.  */
  416.     strncpy(tmpbuf, name, pathlen);
  417.  
  418. #define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
  419.     if (   try("RCS/%s%s", filebase, RCSSUFFIX)
  420.         || try("RCS/%s"  , filebase,         0)
  421.         || try(    "%s%s", filebase, RCSSUFFIX)
  422.         || try("SCCS/%s%s", SCCSPREFIX, filebase)
  423.         || try(     "%s%s", SCCSPREFIX, filebase))
  424.       return name;
  425.     free(name);
  426.     name = Nullch;
  427.     }
  428.  
  429.     return name;
  430. }
  431.  
  432. char *
  433. xmalloc (size)
  434.      unsigned size;
  435. {
  436.   register char *p = (char *) malloc (size);
  437.   if (!p)
  438.     fatal("out of memory");
  439.   return p;
  440. }
  441.